package services

import (
    "context"
    "volux/internal/models"
    "volux/pkg/errors"
    "volux/pkg/spdk"
)

// BdevService 提供块设备管理功能
type BdevService struct {
    spdkClient *spdk.Client
    store      *StorageService
    ctx        context.Context
}

// NewBdevService 创建BdevService实例
func NewBdevService(ctx context.Context, client *spdk.Client, store *StorageService) *BdevService {
    return &BdevService{
        ctx:        ctx,
        spdkClient: client,
        store:      store,
    }
}

// CreateBdev 创建块设备
func (s *BdevService) CreateBdev(bdev *models.Bdev) error {
    // 前置处理
    if err := bdev.BeforeCreate(); err != nil {
        return err
    }

    // 开启事务
    tx, err := s.store.BeginTx(s.ctx)
    if err != nil {
        return errors.Wrap(err, errors.ErrTypeIO, 500, "failed to begin transaction")
    }
    defer tx.Rollback()

    // 创建SPDK设备
    if err := s.createSPDKBdev(bdev); err != nil {
        return err
    }

    // 持久化存储
    if err := s.store.SaveBdev(tx, bdev); err != nil {
        // 回滚SPDK操作
        if rbErr := s.spdkClient.DeleteBdev(bdev.Name); rbErr != nil {
            // 记录回滚失败但不返回这个错误
            log.Errorf("Failed to rollback bdev creation: %v", rbErr)
        }
        return errors.Wrap(err, errors.ErrTypeIO, 500, "failed to save bdev")
    }

    return tx.Commit()
}

// createSPDKBdev 创建SPDK块设备
func (s *BdevService) createSPDKBdev(bdev *models.Bdev) error {
    var err error
    switch bdev.Type {
    case models.BdevTypeMalloc:
        err = s.spdkClient.CreateMallocBdev(bdev.Name, bdev.SizeMB)
    case models.BdevTypeAio:
        err = s.spdkClient.CreateAioBdev(bdev.Name, bdev.Filename)
    case models.BdevTypeNVMe:
        err = s.spdkClient.CreateNVMeBdev(bdev.Name, bdev.Traddr, bdev.Transport)
    default:
        return errors.New(errors.ErrTypeParam, 400, "unsupported bdev type")
    }

    if err != nil {
        return errors.Wrap(err, errors.ErrTypeRuntime, 500, "failed to create spdk bdev")
    }
    return nil
}
